package org.dragonnova.lamp.service;

import android.content.Context;
import android.os.SystemClock;

import org.dragonnova.lamp.ErrorCode;
import org.dragonnova.lamp.Lamp;
import org.dragonnova.lamp.LampGroup;
import org.dragonnova.lamp.LampManager;
import org.dragonnova.lamp.MessageDelivery;
import org.dragonnova.lamp.PhoneInfo;
import org.dragonnova.lamp.ProtocolDefined;
import org.dragonnova.lamp.Tap;
import org.dragonnova.lamp.TapManager;
import org.dragonnova.lamp.message.IMessage;
import org.dragonnova.lamp.message.IProtocol;
import org.dragonnova.lamp.message.Message;
import org.dragonnova.lamp.utils.ByteUtil;
import org.dragonnova.lamp.utils.HexUtil;
import org.dragonnova.lamp.utils.LogUtil;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Created by hucn on 2016/7/29.
 * Description: 管理与设备的wifi连接,使用udp进行搜索和确认，使用tcp连接进行点和命令数据的传播
 */
public class UDPService implements IService {

    private final String TAG = UDPService.class.getSimpleName();

    private Context mContext;

    private static final int UDP_CLIENT_PORT = 12341; // 本地端口

    private static final int UDP_DEVICE_PORT = 12342; // 远程端口

    private DatagramSocket mUdpSocket;

    private UdpSendThread mUdpSendThread;

    private QueryThread mQueryThread;

    private UdpReceiveThread mUdpReceiveThread;

    private PhoneInfo mLocalInfo;

    private final int VOICE_MAX_QUEUE_SIZE = 200;

    private LinkedBlockingQueue<DatagramPacket> mUdpSendQueue = new LinkedBlockingQueue<>(VOICE_MAX_QUEUE_SIZE);

    private MessageDelivery mDelivery;

    private IProtocol mProtocol;

    private LampManager mLampManager;

    private TapManager mTapManager;

    private final int SUCCESS = 0;

    private final int ERROR = -1;

    private static final int DISCOVERY_NONE = 0;
    private static final int DISCOVERY_QUERY_DEVICE_EXIST = 1;
    private static final int DISCOVERY_QUERY_DEVICE_STATUS = 2;

    //private int DiscoveryStatus = DISCOVERY_NONE;

    public UDPService(Context context, IProtocol protocol, MessageDelivery delivery, LampManager lampManager, TapManager tapManager) {
        mContext = context;
        mProtocol = protocol;
        mLocalInfo = PhoneInfo.getInstance(mContext);
        mDelivery = delivery;
        mLampManager = lampManager;
        mTapManager = tapManager;
    }

    /**
     * 初始化时检查网络状况，获取wifi相关信息
     *
     * @return int 错误信息，如果没有错误，返回SUCCESS
     */
    private int init() {
        if (mLocalInfo.checkWifiConnected()) {
            String udp_client_ip = mLocalInfo.getCurrentIP();
            if (udp_client_ip == null || ("0.0.0.0".equals(udp_client_ip))) {
                LogUtil.e(TAG, "Wifi is enabled,but can not get the IP, please check the wifi settings");
                mDelivery.postLampError(new ErrorCode(ErrorCode.ERROR_WIFI, "Wifi is enabled,but can not get the IP" +
                        ", please check the wifi settings"));
                return ERROR;
            }
            return SUCCESS;
        }
        LogUtil.e(TAG, "Wifi is not enable, please check the wifi settings");
        mDelivery.postLampError(new ErrorCode(ErrorCode.ERROR_WIFI, "Wifi is not enable" +
                ", please check the wifi settings"));
        return ERROR;
    }

    /**
     * 初始化接收和发送消息的socket
     *
     * @return int 错误信息，如果没有错误，返回SUCCESS
     */
    private int createUdpSocket() {
        closeUdp();
        int errorCode = SUCCESS;
        try {
            mUdpSocket = new DatagramSocket(UDP_CLIENT_PORT);
        } catch (SocketException e) {
            mDelivery.postLampError(new ErrorCode(ErrorCode.ERROR_WIFI, "Create socket error!"));
            errorCode = ERROR;
            e.printStackTrace();
        }
        return errorCode;
    }

    @Override
    public void start() {
        int errorCode = init();
        if (errorCode == SUCCESS) {
            errorCode = createUdpSocket();
            if (errorCode == SUCCESS) {
                startUdpThreads();
            }
        }
    }

    @Override
    public void stop() {
        clearSocketThreads();
        clearSockets();
    }

    @Override
    public void discovery() {
        mQueryThread = new QueryThread();
        mQueryThread.start();
    }

    @Override
    public void controlLamp(Lamp lamp) {
        if (mUdpSocket != null && mUdpSocket.isBound()) {
            try {
                mUdpSendQueue.put(getControlPacket(getLampControlMessage(lamp), lamp.getIp()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
        }
    }

    @Override
    public void controlTap(Tap tap) {
        if (mUdpSocket != null && mUdpSocket.isBound()) {
            try {
                mUdpSendQueue.put(getControlPacket(getTapControlMessage(tap), tap.getIp()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
        }
    }

    private void startUdpThreads() {
        mUdpSendThread = new UdpSendThread();
        mUdpSendThread.start();
        mUdpReceiveThread = new UdpReceiveThread();
        mUdpReceiveThread.start();
    }

    /**
     * 关闭所有socket
     */
    private void clearSockets() {
        closeUdp();
    }

    private void closeUdp() {
        LogUtil.i(TAG, "Close udp socket");
        if (mUdpSocket != null) {
            mUdpSocket.close();
            mUdpSocket = null;
        }
    }

    /**
     * 关闭所有与TCP和UDP相关的线程Thread
     */
    private void clearSocketThreads() {
        closeUdpThreads();
    }

    private void closeUdpThreads() {
        if (mUdpSendThread != null) {
            mUdpReceiveThread.interrupt();
            mUdpSendThread.finish();
            mUdpSendThread = null;
        }
        if (mUdpReceiveThread != null) {
            mUdpReceiveThread.interrupt();
            mUdpReceiveThread.finish();
            mUdpReceiveThread = null;
        }
        if (mQueryThread != null) {
            mQueryThread.interrupt();
            mQueryThread = null;
        }
    }

    private class QueryThread extends Thread {
        private int count = 0;

        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    if (count % 1 == 0) {
                        if (count < 50) {
                            if (mUdpSocket != null && mUdpSocket.isBound()) {
                                //DiscoveryStatus = DISCOVERY_QUERY_DEVICE_EXIST;
                                try {
                                    for (int i = 0; i < 1; i++) {
                                        mUdpSendQueue.put(getExistPacket(getExisLamptMessage()));
                                        mUdpSendQueue.put(getExistPacket(getExisTaptMessage()));
                                    }
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            } else {
                                LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
                            }
                        }
                        if (mUdpSocket != null && mUdpSocket.isBound()) {
                            //DiscoveryStatus = DISCOVERY_QUERY_DEVICE_STATUS;
                            List<Lamp> lamps = mLampManager.getLamps();
                            boolean hasChangedLamp = false;
                            for (Lamp lamp : lamps) {
                                if (lamp.getControlTime() > lamp.getRefreshTime()) {
                                    hasChangedLamp = true;
                                    controlLamp(lamp);
                                }
                            }
                            if (!hasChangedLamp) {
                                if (count % 10 == 0) {
                                    List<LampGroup> groups = mLampManager.getGroups();
                                    for (LampGroup group : groups) {
                                        mUdpSendQueue.put(getDiscoveryPacket(getLampDiscoveryMessage(group), group.getIp()));
                                    }
                                }
                            }
                            List<Tap> tapList = mTapManager.getLaps();
                            for (Tap tap : tapList) {

                                if (tap.getControlTime() > tap.getRefreshTime()) {
                                    if (count % 6 == 0) {
                                        controlTap(tap);
                                    }
                                } else {
                                    if (count % 10 == 0) {
                                        mUdpSendQueue.put(getDiscoveryPacket(getTapDiscoveryMessage(tap), tap.getIp()));
                                    }
                                }
                            }
                        } else {
                            LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
                        }
                    }
                    count++;
                    LogUtil.e(TAG, "count=" + count);
                    SystemClock.sleep(50);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * UDP消息发送线程
     */
    private class UdpSendThread extends Thread {
        private boolean isStopped = false;

        @Override
        public void run() {
            this.setName(UdpSendThread.class.getName());
            LogUtil.i(TAG, "Udp socket send thread start.");
            try {
                while (!isStopped && !Thread.interrupted()) {
                    DatagramPacket packet = mUdpSendQueue.take();
                    if (packet.getData() == null || packet.getData().length == 0) {
                        continue;
                    }
                    if (mUdpSocket != null && mUdpSocket.isBound()) {
                        try {
                            LogUtil.d(TAG, "Send udp message to device");
                            mUdpSocket.send(packet);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        LogUtil.e(TAG, "The socket is not bounded or is null, discard the message");
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public void finish() {
            isStopped = true;
            try {
                mUdpSendQueue.put(new DatagramPacket(new byte[0], 0));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mUdpSendQueue.clear();
        }
    }

    /**
     * UDP消息接收线程
     */
    private class UdpReceiveThread extends Thread {
        private boolean isStopped = false;
        private byte[] data = new byte[128];

        @Override
        public void run() {
            this.setName(UdpReceiveThread.class.getName());
            while (!isStopped && !Thread.interrupted()) {
                if (mUdpSocket != null && mUdpSocket.isBound()) {
                    DatagramPacket packet = new DatagramPacket(data, data.length);
                    try {
                        mUdpSocket.receive(packet);
                        LogUtil.e(TAG, "receive: " + HexUtil.bytesToString(packet.getData()));
                        parse(packet);
                        data = new byte[128];
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        public void finish() {
            isStopped = true;
        }
    }

    private void parse(DatagramPacket packet) {
        /*int port = packet.getPort();
        if (port != UDP_DEVICE_PORT) {
            return;
        }*/
        byte[] data = packet.getData();
        String ip = packet.getAddress().getHostAddress();
        IMessage message = mProtocol.decode(data);
        //if (DiscoveryStatus == DISCOVERY_QUERY_DEVICE_EXIST) {
        if (message.getAction() == ProtocolDefined.ACTION_DEVICE_REQUEST_INSTORE) {
            if (message.getDeviceType() == ProtocolDefined.TYPE_DEVICE_SWITCH) {
                if (message.getRemoteId() == ProtocolDefined.LOCAL_ID) {
                    LogUtil.e(TAG, "query exist result:" + HexUtil.bytesToString(message.getData()));
                    byte[] members = message.getData();
                    if (members != null && members.length == 1) {
                        int size = (int) members[0];
                        int groupId = (int) ByteUtil.mergeBytes(message.getLocalId(), message.getLocalCommunicationType());
                        LampGroup group = new LampGroup(groupId, ip, size);
                        mLampManager.refresh(group);
                        LampstorageResponse(group);
                    } else {
                        LogUtil.e(TAG, "Wrong storage request data size: " + HexUtil.bytesToString(message.getData()));
                    }
                } else {
                    LogUtil.e(TAG, "Wrong phone id: " + message.getRemoteId());
                }
            } else if (message.getDeviceType() == ProtocolDefined.TYPE_DEVICE_TAP) {
                if (message.getRemoteId() == ProtocolDefined.LOCAL_ID) {
                    LogUtil.e(TAG, "query exist result:" + HexUtil.bytesToString(message.getData()));
                    byte[] members = message.getData();
                    if (members != null && members.length == 1) {
                        int size = (int) members[0];
                        int tapId = (int) ByteUtil.mergeBytes(message.getLocalId(), message.getLocalCommunicationType());
                        LogUtil.e(TAG, "tap is :" + tapId);
                        Tap tap = new Tap();
                        tap.setId(tapId);
                        tap.setIp(ip);
                        mTapManager.refresh(tap);
                        TapstorageResponse(tap);
                    } else {
                        LogUtil.e(TAG, "Wrong storage request data size: " + HexUtil.bytesToString(message.getData()));
                    }
                } else {
                    LogUtil.e(TAG, "Wrong phone id: " + message.getRemoteId());
                }
            } else {
                LogUtil.e(TAG, "Wrong device type: " + message.getDeviceType());
            }
        } else {
            LogUtil.e(TAG, "Wrong action type: " + HexUtil.bytesToString(new byte[]{message.getAction()}));
        }
        //}
        //if (DiscoveryStatus == DISCOVERY_QUERY_DEVICE_STATUS) {
        if (message.getAction() == ProtocolDefined.ACTION_DEVICE_RESPONSE) {
            if (message.getDeviceType() == ProtocolDefined.TYPE_DEVICE_SWITCH) {
                if (message.getRemoteId() == ProtocolDefined.LOCAL_ID) {
                    byte[] statusBytes = message.getData();
                    if (statusBytes.length == 2) {
                        int groupId = (int) ByteUtil.mergeBytes(message.getLocalId(), message.getLocalCommunicationType());
                        mLampManager.refresh(groupId, statusBytes);
                        mDelivery.postLampResponse(mLampManager.getLamps());
                    } else {
                        LogUtil.e(TAG, "Wrong data size: " + HexUtil.bytesToString(statusBytes));
                    }
                } else {
                    LogUtil.e(TAG, "Wrong phone id: " + message.getRemoteId());
                }
            } else if (message.getDeviceType() == ProtocolDefined.TYPE_DEVICE_TAP) {
                if (message.getRemoteId() == ProtocolDefined.LOCAL_ID) {
                    byte[] statusBytes = message.getData();
                    if (statusBytes.length == 2) {
                        int id = (int) ByteUtil.mergeBytes(message.getLocalId(), message.getLocalCommunicationType());
                        mTapManager.refresh(id, statusBytes);
                        mDelivery.postTapResponse(mTapManager.getLaps());
                    } else {
                        LogUtil.e(TAG, "Wrong data size: " + HexUtil.bytesToString(statusBytes));
                    }
                } else {
                    LogUtil.e(TAG, "Wrong phone id: " + message.getRemoteId());
                }
            } else {
                LogUtil.e(TAG, "Wrong device type: " + message.getDeviceType());
            }
        } else {
            LogUtil.e(TAG, "Wrong action type: " + message.getAction());
        }
        //}
    }

    /**
     * 发送应答消息
     */
    public void LampstorageResponse(LampGroup group) {
        if (mUdpSocket != null && mUdpSocket.isBound()) {
            try {
                mUdpSendQueue.put(getStorageResponsePacket(getLampStorageResponseMessage(group), group.getIp()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
        }
    }

    /**
     * 发送应答消息
     */
    public void TapstorageResponse(Tap tap) {
        if (mUdpSocket != null && mUdpSocket.isBound()) {
            try {
                mUdpSendQueue.put(getStorageResponsePacket(getTapStorageResponseMessage(tap), tap.getIp()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            LogUtil.e(TAG, "Can not send message because the socket is null or not bounded!");
        }
    }

    /**
     * 获取搜索包的内容
     */
    private byte[] getExisLamptMessage() {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_QUERY_DEVICE_EXIST);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_SWITCH);
        message.setRemoteId(ProtocolDefined.DEVICE_ID);
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_EXIST);
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Discovery Socket get " + data.length + " size message to send. " + "IP is = " +
                mLocalInfo.getMultiIP() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    private byte[] getExisTaptMessage() {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_QUERY_DEVICE_EXIST);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_TAP);
        message.setRemoteId(ProtocolDefined.DEVICE_ID);
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_EXIST);
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Discovery Socket get " + data.length + " size message to send. " + "IP is = " +
                mLocalInfo.getMultiIP() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    private DatagramPacket getExistPacket(byte[] data) {
        DatagramPacket packet = new DatagramPacket(data, data.length);
        packet.setSocketAddress(new InetSocketAddress(mLocalInfo.getMultiIP(), UDP_DEVICE_PORT));
        return packet;
    }

    /**
     * 获取搜索包的内容
     */
    private byte[] getLampDiscoveryMessage(LampGroup group) {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_QUERY_DEVICE_STATUS);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_SWITCH);
        byte groupid = (byte) group.getGroup();
        //message.setRemoteId((byte) group.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & groupid) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & groupid));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Discovery Socket get " + data.length + " size message to send. " + "IP is = " +
                group.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    private byte[] getTapDiscoveryMessage(Tap tap) {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_QUERY_DEVICE_STATUS);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_TAP);
        byte id = (byte) tap.getId();
        //message.setRemoteId((byte) group.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & id) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & id));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Discovery Socket get " + data.length + " size message to send. " + "IP is = " +
                tap.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }


    private DatagramPacket getDiscoveryPacket(byte[] data, String ip) {
        DatagramPacket packet = new DatagramPacket(data, data.length);
        //packet.setSocketAddress(new InetSocketAddress(ip, UDP_DEVICE_PORT));
        packet.setSocketAddress(new InetSocketAddress(mLocalInfo.getMultiIP(), UDP_DEVICE_PORT));
        return packet;
    }

    /**
     * 获取搜索包的内容
     */
    private byte[] getLampControlMessage(Lamp lamp) {

        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_CONTROL_DEVICE);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_SWITCH);
        byte groupid = (byte) lamp.getGroup();
        //message.setRemoteId((byte) lamp.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & groupid) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & groupid));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] statusBytes = mLampManager.getGroupMap().get(lamp.getGroup()).getStatus();
        byte[] xor = new byte[2];
        int id = lamp.getId();
        if (id <= 7) {
            xor[1] = (byte) ((byte) 0x01 << id);
        } else {
            int j = id - 8;
            xor[0] = (byte) ((byte) 0x01 << j);
        }
        byte[] sendStatusBytes = new byte[]{(byte) (statusBytes[0] ^ xor[0]), (byte) (statusBytes[1] ^ xor[1])};
        LogUtil.e(TAG, "before:" + HexUtil.bytesToString(statusBytes));
        LogUtil.e(TAG, "after:" + HexUtil.bytesToString(sendStatusBytes));

        message.setData(sendStatusBytes);

        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Control Socket get " + data.length + " size message to send. " + "IP is = " +
                lamp.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    /**
     * 获取搜索包的内容
     */
    private byte[] getTapControlMessage(Tap tap) {

        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_CONTROL_DEVICE);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_TAP);
        byte id = (byte) tap.getId();
        //message.setRemoteId((byte) lamp.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & id) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & id));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] statusBytes;
        if (tap.getControlStatus() == Tap.ON) {
            statusBytes = new byte[]{0x00, 0x01};
        } else {
            statusBytes = new byte[]{0x00, 0x00};
        }
        LogUtil.e(TAG, "before:" + HexUtil.bytesToString(statusBytes));

        message.setData(statusBytes);

        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "Control Socket get " + data.length + " size message to send. " + "IP is = " +
                tap.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    private DatagramPacket getControlPacket(byte[] data, String ip) {
        DatagramPacket packet = new DatagramPacket(data, data.length);
        //packet.setSocketAddress(new InetSocketAddress(ip, UDP_DEVICE_PORT));
        packet.setSocketAddress(new InetSocketAddress(mLocalInfo.getMultiIP(), UDP_DEVICE_PORT));
        return packet;
    }


    /**
     * 获取回应包的内容
     */
    private byte[] getLampStorageResponseMessage(LampGroup group) {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_DEVICE_RESPONSE);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_SWITCH);
        byte groupid = (byte) group.getGroup();

        //message.setRemoteId((byte) group.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & groupid) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & groupid));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "StorageResponse Socket get " + data.length + " size message to send. " + "IP is = " +
                group.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }

    /**
     * 获取回应包的内容
     */
    private byte[] getTapStorageResponseMessage(Tap tap) {
        Message message = new Message();
        message.setAction(ProtocolDefined.ACTION_DEVICE_RESPONSE);
        message.setDeviceType(ProtocolDefined.TYPE_DEVICE_TAP);
        byte id = (byte) tap.getId();

        //message.setRemoteId((byte) group.getGroup());
        message.setRemoteId((byte) (((byte) 0xF0 & id) >> 4));
        message.setLocalId(ProtocolDefined.LOCAL_ID);
        //message.setRemoteCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_WIFI);
        message.setRemoteCommunicationType((byte) ((byte) 0x0F & id));
        message.setLocalCommunicationType(ProtocolDefined.TYPE_COMMUNICATION_MASTER);
        byte[] data = mProtocol.encode(message);
        LogUtil.i(TAG, "StorageResponse Socket get " + data.length + " size message to send. " + "IP is = " +
                tap.getIp() + " ,The message is: " + HexUtil.bytesToString(data));
        return data;
    }


    private DatagramPacket getStorageResponsePacket(byte[] data, String ip) {
        DatagramPacket packet = new DatagramPacket(data, data.length);
        //packet.setSocketAddress(new InetSocketAddress(ip, UDP_DEVICE_PORT));
        packet.setSocketAddress(new InetSocketAddress(mLocalInfo.getMultiIP(), UDP_DEVICE_PORT));
        return packet;
    }
}
